/*
 * Copyright 2006-2007 the original author or authors.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.google.code.sant;

import org.apache.tools.ant._

import org.apache.tools.ant.types._
import org.apache.tools.ant.taskdefs._

/**
 * Base class to type and task.
 *
 * @author Stepan Koltsov
 */
abstract class AntProjectComponent(project: Project, clazz: Class) {
  type PCT <: ProjectComponent
  
  def populate(task: AnyRef, args: AntParam*) {
    val ih = IntrospectionHelper.getHelper(task.getClass)
    for (param <- args) {
      param match {
        case p @ AnyAntParam(name, _) =>
          ih.setAttribute(project, task, name, p.valueString)
          
        case p: DataTypeAntParam =>
          //val elementName = project.getElementName(p.dataType)
          val elementName = p.name
          
          //if (!ih.supportsNestedElement(elementName)) throw new SantException("nested " + elementName + " are not supported")
          
          // does not work?
          //ih.storeElement(project, task, p.dataType, elementName)
          
          val method = ih.getElementMethod(elementName)
          if (method.getParameterTypes.length != 1)
            throw new Exception("don't know what to do with method " + method + " (XXX)")
          Logger.verbose("about to invoke method " + method)
          method.invoke(task, Array(p.dataType))
          
          //println("stored " + p.dataType + "(" + p.dataType.getClass.getName + ") as " + elementName)
          //println(ih.getNestedElementMap)
          
          //task.asInstanceOf[Copy].addFileset(p.dataType.asInstanceOf[FileSet])
        
        case p: NestedElementAntParam =>
          val child = ih.createElement(project, task, p.name)
          populate(child, p.params: _*)
        
        case _ => throw new SantException("unknown param " + param)
      }
    }
  }
  
  def create(args: AntParam*) = {
    val task = clazz.newInstance().asInstanceOf[PCT]
    task.setProject(project)
    
		populate(task, args: _*)

    task
  }

}
